package neuron;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import neuron.geometry.CoordSet;

public class Neuron {
	
	/**
	 * Soma (cell body) of neuron
	 */
	private Soma soma;
	
	/**
	 * Axon
	 */
	private Dendrite axon;
	
	/**
	 * Basal dendrites
	 */
	private List<Dendrite> basalDendrites;
	
	/**
	 * Apical dendrite
	 */
	private Dendrite apicalDendrite;

		
	/**
	 * Other (meta)data
	 */
	private Map<String, Object> metadata;
	
	/**
	 * Load errors
	 */
	private List<String> errors;
	
	/**
	 * Network this neurons is part of.
	 */
	private Network network;
	
	public Neuron() {
		basalDendrites = new ArrayList<Dendrite>();
		metadata = new HashMap<String, Object>();
		errors = new ArrayList<String>();
	}
	
	/**
	 * Mark error that occured during loading
	 * @param err
	 */
	public void error(String err) 
	{
		errors.add(err);
	}
	
	public void addMetadata(String key, Object data)
	{
		metadata.put(key, data);
	}
	
	public Object getMetadata(String key)
	{
		return metadata.get(key);
	}
	
	public void removeMetadata(String key)
	{
		metadata.remove(key);
	}
	
	public Soma getSoma() {
		return soma;
	}

	public void setSoma(Soma soma) {
		this.soma = soma;
	}

	public Dendrite getAxon() {
		return axon;
	}

	public void setAxon(Dendrite axon) {
		this.axon = axon;
	}

	public Dendrite getApicalDendrite() {
		return apicalDendrite;
	}

	public void setApicalDendrite(Dendrite apicalDendrite) {
		this.apicalDendrite = apicalDendrite;
	}
	
	public void addBasalDendrite(Dendrite d) {
		basalDendrites.add(d);
	}
	
	public void removeBasalDendrite(Dendrite d) {
		basalDendrites.remove(d);
	}
	
	public List<Dendrite> basalDendrites()
	{
		return basalDendrites;
	}
	
	public List<Dendrite> allDendrites()
	{
		List<Dendrite> lst = new ArrayList<Dendrite>(basalDendrites);
		lst.add(apicalDendrite);
		return lst;
	}

	public CoordSet getAllCoordinates()
	{
		CoordSet coords = new CoordSet();
		
		// soma
		coords.addAll(soma.getPoints());
		
		// dendrites & axon
		for (Dendrite d : basalDendrites) {
			coords.addAll(d.getAllCoordinates());
		}
		if (apicalDendrite != null) coords.addAll(apicalDendrite.getAllCoordinates());
		if (axon != null) coords.addAll(axon.getAllCoordinates());
	
		return coords;
	}
	
	@Override
	public String toString() {
		return "Neuron with " + basalDendrites.size() + " basal dendrites.";
	}

	public Network getNetwork() {
		return network;
	}

	public void setNetwork(Network network) {
		this.network = network;
	}
	
	public List<Coord> getAllBasalCoordinates()
	{
		List<Coord> allCoord = new ArrayList<Coord>();
		List<Dendrite> lst = basalDendrites();
		for (Dendrite d : lst) {
			allCoord.addAll(d.getAllCoordinates());
		}
		return allCoord;
	}
	
	public NeuronStatistics statistics()
	{
		return new NeuronStatistics(this);
	}
}
